package view.visualizations;

import java.util.Date;

import prefuse.Constants;
import prefuse.action.ActionList;
import prefuse.action.RepaintAction;
import prefuse.action.assignment.DataColorAction;
import prefuse.action.layout.AxisLabelLayout;
import prefuse.action.layout.AxisLayout;
import prefuse.data.expression.AndPredicate;
import prefuse.data.expression.ColumnExpression;
import prefuse.data.expression.ComparisonPredicate;
import prefuse.data.expression.ObjectLiteral;
import prefuse.data.expression.Predicate;
import prefuse.data.util.Sort;
import prefuse.render.AbstractShapeRenderer;
import prefuse.render.AxisRenderer;
import prefuse.render.Renderer;
import prefuse.render.RendererFactory;
import prefuse.render.ShapeRenderer;
import prefuse.visual.VisualItem;
import prefuse.visual.VisualTable;
import prefuse.visual.expression.VisiblePredicate;
import view.renderers.PointRenderer;
import view.renderers.TeamColorAction;
import data.DataManager;

/**
 * This class is kind of weird because there's no actual visualization. It's just used
 * to filter the table.
 */
public class RaceTableVis extends XCVis {

	private Date date;
	private String meet;
	private String race;
	
	public RaceTableVis(final Date date, final String meet, final String race) {
		super();
		this.date = date;
		this.meet = meet;
		this.race = race;
		this.removeGroup("data");
		Predicate datePredicate = new ComparisonPredicate(
				ComparisonPredicate.EQ, new ColumnExpression("Date"), new ObjectLiteral(date));
		Predicate meetPredicate = new ComparisonPredicate(
				ComparisonPredicate.EQ, new ColumnExpression("Meet"), new ObjectLiteral(meet));
		Predicate racePredicate = new ComparisonPredicate(
				ComparisonPredicate.EQ, new ColumnExpression("Race"), new ObjectLiteral(race));
		originalPredicate = new AndPredicate(new AndPredicate(datePredicate, meetPredicate),
				racePredicate);
		System.out.println("Pred: " + originalPredicate.toString());
		String[] sortOrder = {"Place"};
		DataManager.getInstance().setSortOrder(sortOrder);
		tupleSet = addTable("data", DataManager.getInstance().getTable(), originalPredicate);
//		tupleSet = addTable("data", DataManager.getInstance().getSortedTable(new Sort(sortOrder)), originalPredicate);
		
		xAxis = new AxisLayout("data", "Place", Constants.X_AXIS,
				VisiblePredicate.TRUE);
 
		yAxis = new AxisLayout("data", "Time", Constants.Y_AXIS,
				VisiblePredicate.TRUE);
		
		setupVis();
	}
	
	public Date getDate() {
		return date;
	}
	public String getMeet() {
		return meet;
	}
	public String getRace() {
		return race;
	}
	
	@Override
	public void setupVis() {

		AxisLabelLayout x_labels = new AxisLabelLayout("xlab", xAxis);
		AxisLabelLayout y_labels = new AxisLabelLayout("ylab", yAxis);
		
		TeamColorAction color = new TeamColorAction("data", "School", Constants.NOMINAL, 
				VisualItem.STROKECOLOR, this);
		
		ActionList draw = new ActionList();
		draw.add(xAxis);
		draw.add(yAxis);
		draw.add(x_labels);
		draw.add(y_labels);
		draw.add(color);
		
		this.setRendererFactory(new RendererFactory() {
			PointRenderer pr = new PointRenderer(RaceTableVis.this);
			Renderer arY = new AxisRenderer(Constants.FAR_LEFT,
					Constants.CENTER);
			Renderer arX = new AxisRenderer(Constants.CENTER,
					Constants.FAR_BOTTOM);
 
			public Renderer getRenderer(VisualItem item) {
				
				return item.isInGroup("ylab") ? arY
						: item.isInGroup("xlab") ? arX : pr;
			}
		});
		
		draw.add(new RepaintAction());
		this.putAction("draw", draw);
		this.run("draw");

		ActionList update = new ActionList();
		update.add(xAxis);
		update.add(yAxis);
		update.add(x_labels);
		update.add(y_labels);
		update.add(new RepaintAction());
		this.putAction("update", update);

		this.repaint();
	}
	
	/**
	 * This is necessary because of the weird way that prefuse treats filters. Filters applied
	 * after the creation of the table seem to be treated differently than filters applied when
	 * the table is created. So, to get the JTable to work, we need to create a new table with an
	 * updated filter. Surely there's a better way to do this.
	 */
	public void filterTable(final Predicate p) {
		this.removeGroup("data");
		if (p==null) {
			tupleSet = addTable("data", DataManager.getInstance().getTable(), originalPredicate);
			return;
		}
		Predicate finalPredicate = new AndPredicate(originalPredicate, p);
		System.out.println("final Pred: " + finalPredicate.toString());
		this.removeGroup("data");
		tupleSet = addTable("data", DataManager.getInstance().getTable(), finalPredicate);
	}
	
	public VisualTable getVisualTable() {
		return tupleSet;
	}

}
